package com.ruoyi.framework.web.service;

import cn.hutool.json.JSONObject;
import com.ruoyi.common.config.ExternalInterfaceConfig;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.DeviceCategory;
import com.ruoyi.common.enums.DeviceStatus;
import com.ruoyi.common.enums.PushStatus;
import com.ruoyi.common.enums.RequestMapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.RequestService;
import com.ruoyi.fire.domain.DWaterMessage;
import com.ruoyi.fire.domain.TDevice;
import com.ruoyi.fire.domain.TUnit;
import com.ruoyi.fire.service.*;
import com.ruoyi.framework.web.domain.TemplateMsgEntity;
import com.ruoyi.system.service.ISysDictTypeService;
import com.ruoyi.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @PackageName: com.ruoyi.framework.web.service
 * @ClassName: DataSyncService
 * @Description:
 * @Author: czl
 * @Date: 2025/10/30 22:41
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DataSyncService {

    private final IEEconomicTypeService economicTypeService;
    private final IEIndustryBelongService industryBelongService;
    private final IEIndustryService industryService;
    private final IEMaintenanceUnitService maintenanceUnitService;
    private final IERegionService regionService;
    private final IESuperviseLevelService superviseLevelService;
    private final IEUnitTagService unitTagService;
    private final IEUnitTypeService unitTypeService;
    private final IEBuildingFireHazardService eBuildingFireHazardService;
    private final IEBuildingResistantService eBuildingResistantService;
    private final IEBuildingStructureService eBuildingStructureService;
    private final IEBuildingTypeService eBuildingTypeService;
    private final IEBuildingUseWayService eBuildingUseWayService;
    private final IEDeviceDataTypeService eDeviceDataTypeService;
    private final IEDeviceTypeService eDeviceTypeService;
    private final ITDeviceService tDeviceService;
    private final RequestService requestService;
    private final TemplateService templateService;
    private final ISysUserService sysUserService;
    private final ITUnitService unitService;
    private final ISysDictTypeService dictTypeService;
    private final IDWaterMessageService waterMessageService;
    private final RestTemplate restTemplate;
    private final ExternalInterfaceConfig externalInterfaceConfig;

    public void dataSync() {
        // 定义需要同步的服务任务列表
        List<Runnable> syncTasks = Arrays.asList(
                () -> safeExecute("单位所属行业分类", industryBelongService::dataSync),
                () -> safeExecute("经济类型", economicTypeService::dataSync),
                () -> safeExecute("行业类别", industryService::dataSync),
                () -> safeExecute("维保单位", maintenanceUnitService::dataSync),
                () -> safeExecute("区域", regionService::dataSync),
                () -> safeExecute("监管级别", superviseLevelService::dataSync),
                () -> safeExecute("单位标签", unitTagService::dataSync),
                () -> safeExecute("单位类型", unitTypeService::dataSync),
                () -> safeExecute("筑物火灾危险性", eBuildingFireHazardService::dataSync),
                () -> safeExecute("建筑物耐火等级", eBuildingResistantService::dataSync),
                () -> safeExecute("建筑物结构类型", eBuildingStructureService::dataSync),
                () -> safeExecute("建筑物类型", eBuildingTypeService::dataSync),
                () -> safeExecute("建筑物使用性质", eBuildingUseWayService::dataSync),
                () -> safeExecute("数据类型", eDeviceDataTypeService::dataSync),
                () -> safeExecute("设备类型", eDeviceTypeService::dataSync)
        );

        // 使用共享线程池执行所有任务 控制并发数，避免过多线程竞争
        ExecutorService executorService = Executors.newFixedThreadPool(Math.min(syncTasks.size(), 4));

        try {
            // 并行执行所有同步任务
            List<CompletableFuture<Void>> futures = syncTasks.stream()
                    .map(task -> CompletableFuture.runAsync(task, executorService))
                    .collect(Collectors.toList());

            // 等待所有任务完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

        } catch (Exception e) {
            log.error("数据同步过程中出现异常", e);
        } finally {
            executorService.shutdown();
        }
    }

    /**
     * 安全执行同步任务，统一处理异常
     */
    private void safeExecute(String taskName, Runnable task) {
        try {
            long startTime = System.currentTimeMillis();
            task.run();
            long endTime = System.currentTimeMillis();
            log.info("{}数据同步完成，耗时: {}ms", taskName, endTime - startTime);
        } catch (Exception e) {
            log.error("{}数据同步失败", taskName, e);
        }
    }

    /**
     * 心跳数据上报同步
     */
    public void heartbeatDataReportedSync() {
        List<TDevice> gatewayDevices = tDeviceService.enableDeviceWatchPushList(DeviceStatus.ENABLE, DeviceCategory.GATEWAY);

        if (!CollectionUtils.isEmpty(gatewayDevices)) {
            for (TDevice gatewayDevice : gatewayDevices) {
                try {
                    //ResponseEntity<String> responseEntity = restTemplate.getForEntity(externalInterfaceConfig.getDeviceOnlineUrl() + gatewayDevice.getDeviceCode(), String.class);

                    //if (responseEntity.getStatusCode()  == HttpStatus.OK){
                        //String responseEntityBody = responseEntity.getBody();
                        if (null != gatewayDevice.getDeviceId() && !gatewayDevice.getDeviceId().trim().isEmpty() /*&& responseEntityBody == "true"*/) {
                            Map<String, Object> params = new HashMap<>();
                            // 设备id,创建设备时获得
                            params.put("device_id", gatewayDevice.getDeviceId());
                            // 上报时间（要求为当前时间十分钟之内）
                            params.put("reported_at", String.valueOf(System.currentTimeMillis()));
                            // 数据类型（201-火灾报警心跳数据 ✳数据类型字典获取）
                            params.put("data_type_id", "201");

                            requestService.advancedRequest(RequestMapper.HEARTBEAT_DATA, params);
                        }
                    //}
                } catch (Exception e) {
                    // 记录单个设备请求异常，避免影响其他设备
                    System.err.println("设备心跳数据上报失败，设备ID: " + gatewayDevice.getDeviceId() + ", 错误信息: " + e.getMessage());
                }
            }
        }

    }

    /**
     * 微信模板消息通知
     */
    public void watchTemplateNotice() {

        List<TDevice> gatewayDevices = tDeviceService.enableDeviceWatchPushList(DeviceStatus.ENABLE, DeviceCategory.WATER, PushStatus.PUSH_SUCCESSFUL);
        if (CollectionUtils.isEmpty(gatewayDevices)) return;

        List<SysUser> sysUsers = sysUserService.selectUserOpenId();
        if (CollectionUtils.isEmpty(sysUsers)) return;

        List<SysDictData> dictDeviceNameDataList = dictTypeService.selectDictDataByType("device_name");

        Map<String, String> deviceNameToLabelMap = dictDeviceNameDataList.stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel, (v1, v2) -> v1));

        String accessToken = templateService.getAccessToken();

        for (TDevice gatewayDevice : gatewayDevices) {

            if (gatewayDevice == null || gatewayDevice.getUnitId() == null || gatewayDevice.getDeviceName() == null || gatewayDevice.getDeviceCode() == null) {
                log.warn("发现非法设备信息: {}", gatewayDevice);
                continue;
            }

            String deviceLabel = deviceNameToLabelMap.get(gatewayDevice.getDeviceName());
            if (deviceLabel == null) {
                log.error("无效的设备名称：{}", gatewayDevice.getDeviceName());
                continue;
            }

            TUnit unit = unitService.getById(gatewayDevice.getUnitId());
            if (unit == null || unit.getUnitName() == null) {
                log.warn("无法找到有效的单位信息，设备ID={}", gatewayDevice.getId());
                continue;
            }

            DWaterMessage waterMessage = waterMessageService.selectLastOneByDeviceNo(gatewayDevice.getDeviceCode());

            if (waterMessage == null) {
                log.warn("无法找到有效的水表数据，设备ID={}", gatewayDevice.getId());
                continue;
            }

            TemplateMsgEntity templateMsgEntity = buildTemplateMsgEntity(unit.getUnitName(), deviceLabel, gatewayDevice.getDeviceCode());

            for (SysUser sysUser : sysUsers) {
                if (sysUser != null && sysUser.getOpenId() != null) {
                    templateService.sendMsg(templateMsgEntity, accessToken, sysUser.getOpenId());
                }
            }
        }
    }

    private TemplateMsgEntity buildTemplateMsgEntity(String unitName, String deviceLabel, String deviceCode) {
        TemplateMsgEntity entity = new TemplateMsgEntity();
        entity.setThing19(unitName);
        entity.setThing2(deviceLabel);
        entity.setTime4(DateUtils.getTime());
        entity.setPhrase3("离线");

        int endIndex = Math.min(19, deviceCode.length());
        entity.setThing14(deviceCode.substring(0, endIndex));
        return entity;
    }
}
